#include "A_Config.h"

#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
LV_IMG_DECLARE(lua_logo)
class AppLua : public AppBase
{
private:
    /* data */
public:
    AppLua()
    {
        name = "lua";
        title = "Lua";
        description = "一个Lua解释器，目前只能从文件管理器打开";
        image = &lua_logo;
    }
    void setup();
    void loop();
    void destruct();
    String param;
    lv_obj_t *txt_debug;
    TaskHandle_t taskLua;
    bool luarunning = false;
    lua_State *L;
};

static AppLua app;

extern "C" void lua_printf(const char *format, ...)
{
    va_list argptr;
    va_start(argptr, format);
    char str[1024];
    vsprintf(str, format, argptr);
    LOCKLV();
    lv_obj_add_state(app.txt_debug, LV_STATE_FOCUSED);
    lv_textarea_set_cursor_pos(app.txt_debug, LV_TEXTAREA_CURSOR_LAST);
    lv_textarea_add_text(app.txt_debug, str);
    UNLOCKLV();
    va_end(argptr);
}

extern "C" void lua_clear()
{
    LOCKLV();
    lv_textarea_set_text(app.txt_debug, "");
    UNLOCKLV();
}

extern "C" void lua_input(const char *title, char **buf, bool chinese)
{
    String s = msgbox_string(title, true, false, chinese);
    *buf = (char *)ps_malloc(s.length() + 1);
    memcpy(*buf, s.c_str(), s.length());
    (*buf)[s.length()] = '\0';
}

void task_lua(void *)
{
    app.L = luaL_newstate(); /* create state */
    if (app.L == NULL)
    {
        lua_printf("无法初始化虚拟机\n");
        vTaskDelete(NULL);
        return;
    }
    luaL_openlibs(app.L);
    int bRet = luaL_loadfile(app.L, app.param.c_str());
    if (bRet != LUA_OK)
    {
        const char *err = lua_tostring(app.L, -1); // 加载失败
        lua_printf(err);
        lua_close(app.L);
        vTaskDelete(NULL);
        return;
    }
    bRet = lua_pcall(app.L, 0, 0, 0); // 执行脚本
    if (bRet != LUA_OK)
    {
        lua_printf("Error: %d: %s\n", bRet, lua_tostring(app.L, -1));
    }
    lua_close(app.L);
    app.luarunning = false;
    vTaskDelete(NULL);
}

void AppLua::setup()
{
    txt_debug = lv_textarea_create(scr);
    lv_obj_center(txt_debug);
    lv_obj_set_size(txt_debug, lv_pct(100), lv_pct(100));
    lv_obj_set_style_text_font(txt_debug, &lv_font_chinese_16, 0);
    if (appManager.parameter == "")
    {
        param = "/sd/autorun.lua";
    }
    else
        param = "/sd" + appManager.parameter;
    xTaskCreatePinnedToCore(task_lua, "task_lua", 10240, NULL, 0, &taskLua, 0);
    luarunning = true;
}

void AppLua::loop()
{
    AppBase::loop();
}

void AppLua::destruct()
{
    if (luarunning == true)
    {
        luaL_error(L, "Interrupted!");
        while (luarunning)
            vTaskDelay(100);
    }
    luarunning = false;
}
